package com.drg.center.dao;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.drg.center.entity.DrgPatientCaseOutPO;
import com.drg.center.entity.DrgPatientCasePersonInfoPO;
import com.drg.center.entity.enums.CaseSearchTypeEnum;
import com.drg.center.entity.param.*;
import com.drg.center.entity.result.*;
import com.drg.center.mapper.DrgPatientCaseOutExtMapper;
import com.drg.center.mapper.DrgPatientCaseOutMapper;
import com.drg.center.mapper.DrgPatientCasePersonInfoMapper;
import com.guaike.core.mybatis.plugins.BaseDAO;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Repository
@AllArgsConstructor
public class DrgPatientCaseOutDAO extends BaseDAO<DrgPatientCaseOutMapper, DrgPatientCaseOutPO> {

    private final DrgPatientCaseOutExtMapper drgPatientCaseOutExtMapper;
    private final DrgPatientCasePersonInfoMapper drgPatientCasePersonInfoMapper;

    public List<MedicalSettlePageVO> findPageList(Integer start, MedicalSettlePageDTO param) {
        return drgPatientCaseOutExtMapper.findPageList(start, param);
    }

    public long findPageCount(MedicalSettlePageDTO param) {
        return drgPatientCaseOutExtMapper.findPageCount(param);
    }

    public int noneUpload(List<String> caseCodeList) {
        LambdaUpdateWrapper<DrgPatientCaseOutPO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DrgPatientCaseOutPO::getIsNone, Boolean.TRUE);
        updateWrapper.eq(DrgPatientCaseOutPO::getStatus, Boolean.FALSE);
        updateWrapper.eq(DrgPatientCaseOutPO::getIsNone, Boolean.FALSE);
        updateWrapper.in(DrgPatientCaseOutPO::getCaseCode, caseCodeList);
        return getBaseMapper().update(new DrgPatientCaseOutPO(), updateWrapper);
    }

    public List<CaseOutMonitorPageVO> findOutPageList(Integer start, CaseOutMonitorPageDTO param) {
        return drgPatientCaseOutExtMapper.findOutPageList(start, param);
    }

    public long findOutPageCount(CaseOutMonitorPageDTO param) {
        return drgPatientCaseOutExtMapper.findOutPageCount(param);
    }

    public List<CaseProfitLossPageVO> caseProfitLossPageList(Integer start, CaseProfitLossDTO param) {
        return drgPatientCaseOutExtMapper.caseProfitLossPageList(start, param);
    }

    public long caseProfitLossPageCount(CaseProfitLossDTO param) {
        return drgPatientCaseOutExtMapper.caseProfitLossPageCount(param);
    }

    public Page<DrgPatientCaseOutPO> medicalProtestStat(MedicalProtestDTO param) {
        LambdaQueryWrapper<DrgPatientCaseOutPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DrgPatientCaseOutPO::getProtestStatus, Boolean.TRUE);
        if (StringUtils.isNotBlank(param.getDepartCode())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getDepartCode, param.getDepartCode());
        }
        if (StringUtils.isNotBlank(param.getDoctorCode())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getDoctorCode, param.getDoctorCode());
        }
        if (StringUtils.isNotBlank(param.getProtestReason())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getProtestReason, param.getProtestReason());
        }
        if (Objects.nonNull(param.getStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getOutHospitalDate, param.getStartDate());
        }
        if (Objects.nonNull(param.getEndDate())) {
            queryWrapper.le(DrgPatientCaseOutPO::getOutHospitalDate, param.getEndDate());
        }
        queryWrapper.orderByDesc(DrgPatientCaseOutPO::getId);
        return getBaseMapper().selectPage(new Page<>(param.getPageIndex(), param.getPageSize()), queryWrapper);
    }

    public long countTotalCase(MedicalSettleDTO param) {
        LambdaQueryWrapper<DrgPatientCaseOutPO> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(param.getSearch())) {
            LambdaQueryWrapper<DrgPatientCasePersonInfoPO> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.like(DrgPatientCasePersonInfoPO::getPatientName, param.getSearch());
            List<DrgPatientCasePersonInfoPO> infoPOS = drgPatientCasePersonInfoMapper.selectList(queryWrapper1);
            List<String> caseCodes = infoPOS.stream().map(DrgPatientCasePersonInfoPO::getCaseCode).collect(Collectors.toList());
            queryWrapper.and(wrapper -> wrapper.like(DrgPatientCaseOutPO::getCaseCode, param.getSearch())
                    .or().like(DrgPatientCaseOutPO::getDoctorName, param.getSearch()).or().in(CollectionUtils.isNotEmpty(caseCodes), DrgPatientCaseOutPO::getCaseCode, caseCodes));
        }
        if (Objects.nonNull(param.getSettleStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getSettleDate, param.getSettleStartDate());
        }
        if (Objects.nonNull(param.getSettleEndDate())) {
            queryWrapper.lt(DrgPatientCaseOutPO::getSettleDate, param.getSettleEndDate());
        }
        if (Objects.nonNull(param.getInStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getInHospitalDate, param.getInStartDate());
        }
        if (Objects.nonNull(param.getInEndDate())) {
            queryWrapper.lt(DrgPatientCaseOutPO::getInHospitalDate, param.getInEndDate());
        }
        if (StringUtils.isNotBlank(param.getDepartCode())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getDepartCode, param.getDepartCode());
        }
        if (StringUtils.isNotBlank(param.getMedicareType())) {
            LambdaQueryWrapper<DrgPatientCasePersonInfoPO> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(DrgPatientCasePersonInfoPO::getMedicareType, param.getMedicareType());
            List<DrgPatientCasePersonInfoPO> infoPOS = drgPatientCasePersonInfoMapper.selectList(queryWrapper1);
            List<String> caseCodes = infoPOS.stream().map(DrgPatientCasePersonInfoPO::getCaseCode).collect(Collectors.toList());
            queryWrapper.in(CollectionUtils.isNotEmpty(caseCodes), DrgPatientCaseOutPO::getCaseCode, caseCodes);
        }
        if (Objects.nonNull(param.getType())) {
            if (param.getType().equals(CaseSearchTypeEnum.noUpload.getCode())) {
                queryWrapper.eq(DrgPatientCaseOutPO::getStatus, Boolean.FALSE);
            } else if (param.getType().equals(CaseSearchTypeEnum.upload.getCode())) {
                queryWrapper.eq(DrgPatientCaseOutPO::getStatus, Boolean.TRUE);
            } else if (param.getType().equals(CaseSearchTypeEnum.auditException.getCode())) {

            } else if (param.getType().equals(CaseSearchTypeEnum.noSettle.getCode())) {
                queryWrapper.isNull(DrgPatientCaseOutPO::getSettleDate);
            } else if (param.getType().equals(CaseSearchTypeEnum.none.getCode())) {
                queryWrapper.eq(DrgPatientCaseOutPO::getChsDrgCode, "0000");
            } else {
                queryWrapper.eq(DrgPatientCaseOutPO::getChsDrgCode, "QY");
            }
        }
        return getBaseMapper().selectCount(queryWrapper);
    }

    // 求病例总费用
    public BigDecimal totalCost(String drgCode) {
        return drgPatientCaseOutExtMapper.totalCost(drgCode);
    }

    // 求病例总数
    public long totalCount(String drgCode) {
        return drgPatientCaseOutExtMapper.totalCount(drgCode);
    }

    //求平均总费用
    public BigDecimal avgCost(String drgCode) {
        return drgPatientCaseOutExtMapper.avgCost(drgCode);
    }

    //求平均住院费用
    public BigDecimal avgInHospitalCost(String drgCode) {
        return drgPatientCaseOutExtMapper.avgInHospitalCost(drgCode);
    }

    public long outHospitalTotalCase(CaseOutMonitorPageDTO param) {
        LambdaQueryWrapper<DrgPatientCaseOutPO> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(param.getSearch())) {
            LambdaQueryWrapper<DrgPatientCasePersonInfoPO> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.like(DrgPatientCasePersonInfoPO::getPatientName, param.getSearch());
            List<DrgPatientCasePersonInfoPO> infoPOS = drgPatientCasePersonInfoMapper.selectList(queryWrapper1);
            List<String> caseCodes = infoPOS.stream().map(DrgPatientCasePersonInfoPO::getCaseCode).collect(Collectors.toList());
            queryWrapper.and(wrapper -> wrapper.like(DrgPatientCaseOutPO::getCaseCode, param.getSearch())
                    .or().like(DrgPatientCaseOutPO::getDoctorName, param.getSearch()).or().in(CollectionUtils.isNotEmpty(caseCodes), DrgPatientCaseOutPO::getCaseCode, caseCodes));
        }
        if (Objects.nonNull(param.getSettleStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getSettleDate, param.getSettleStartDate());
        }
        if (Objects.nonNull(param.getSettleEndDate())) {
            queryWrapper.lt(DrgPatientCaseOutPO::getSettleDate, param.getSettleEndDate());
        }
        if (StringUtils.isNotBlank(param.getDepartCode())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getDepartCode, param.getDepartCode());
        }
        if (StringUtils.isNotBlank(param.getMedicareType())) {
            LambdaQueryWrapper<DrgPatientCasePersonInfoPO> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(DrgPatientCasePersonInfoPO::getMedicareType, param.getMedicareType());
            List<DrgPatientCasePersonInfoPO> infoPOS = drgPatientCasePersonInfoMapper.selectList(queryWrapper1);
            List<String> caseCodes = infoPOS.stream().map(DrgPatientCasePersonInfoPO::getCaseCode).collect(Collectors.toList());
            queryWrapper.in(CollectionUtils.isNotEmpty(caseCodes), DrgPatientCaseOutPO::getCaseCode, caseCodes);
        }
        if (Objects.nonNull(param.getType())) {
            if (param.getType().equals(CaseSearchTypeEnum.noUpload.getCode())) {
                queryWrapper.eq(DrgPatientCaseOutPO::getStatus, Boolean.FALSE);
            } else if (param.getType().equals(CaseSearchTypeEnum.upload.getCode())) {
                queryWrapper.eq(DrgPatientCaseOutPO::getStatus, Boolean.TRUE);
            }
        }
        if (StringUtils.isNotBlank(param.getChsDrgCode())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getChsDrgCode, param.getChsDrgCode());
        }
        return getBaseMapper().selectCount(queryWrapper);
    }

    public BigDecimal outHospitalTotalCost(CaseOutMonitorPageDTO param, String fieldName) {
        QueryWrapper<DrgPatientCaseOutPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(" + fieldName + ") as sumValue");
        if (StringUtils.isNotBlank(param.getSearch())) {
            LambdaQueryWrapper<DrgPatientCasePersonInfoPO> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.like(DrgPatientCasePersonInfoPO::getPatientName, param.getSearch());
            List<DrgPatientCasePersonInfoPO> infoPOS = drgPatientCasePersonInfoMapper.selectList(queryWrapper1);
            List<String> caseCodes = infoPOS.stream().map(DrgPatientCasePersonInfoPO::getCaseCode).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(caseCodes)) {
                queryWrapper.and(wrapper -> wrapper.like("case_code", param.getSearch())
                        .or().like("doctor_name", param.getSearch()).or().in("case_code", caseCodes));
            } else {
                queryWrapper.and(wrapper -> wrapper.like("case_code", param.getSearch())
                        .or().like("doctor_name", param.getSearch()));
            }
        }
        if (Objects.nonNull(param.getSettleStartDate())) {
            queryWrapper.ge("settle_date", param.getSettleStartDate());
        }
        if (Objects.nonNull(param.getSettleEndDate())) {
            queryWrapper.lt("settle_date", param.getSettleEndDate());
        }
        if (StringUtils.isNotBlank(param.getDepartCode())) {
            queryWrapper.eq("depart_code", param.getDepartCode());
        }
        if (StringUtils.isNotBlank(param.getMedicareType())) {
            LambdaQueryWrapper<DrgPatientCasePersonInfoPO> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(DrgPatientCasePersonInfoPO::getMedicareType, param.getMedicareType());
            List<DrgPatientCasePersonInfoPO> infoPOS = drgPatientCasePersonInfoMapper.selectList(queryWrapper1);
            List<String> caseCodes = infoPOS.stream().map(DrgPatientCasePersonInfoPO::getCaseCode).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(caseCodes)) {
                queryWrapper.in("case_code", caseCodes);
            }
        }
        if (Objects.nonNull(param.getType())) {
            if (param.getType().equals(CaseSearchTypeEnum.noUpload.getCode())) {
                queryWrapper.eq("status", Boolean.FALSE);
            } else if (param.getType().equals(CaseSearchTypeEnum.upload.getCode())) {
                queryWrapper.eq("status", Boolean.TRUE);
            }
        }
        List<Map<String, Object>> mapList = getBaseMapper().selectMaps(queryWrapper);
        if (!mapList.isEmpty()) {
            return new BigDecimal(mapList.get(0).get("sumValue").toString());
        }
        return new BigDecimal(0);
    }

    public List<CaseMonitorOutCheckVO> checkDrgPage(Integer start, CaseCheckPageDTO param) {
        return drgPatientCaseOutExtMapper.checkDrgPage(start, param);
    }

    public long checkDrgPageCount(CaseCheckPageDTO param) {
        return drgPatientCaseOutExtMapper.checkDrgPageCount(param);
    }

    public List<KeyProjectsTotalStatPageVO> keyProjectsTotalStatPage(Integer start, KeyProjectsTotalStatExcelDTO param) {
        return drgPatientCaseOutExtMapper.keyProjectsTotalStatPage(start, param);
    }

    public long keyProjectsTotalStatPageCount(KeyProjectsTotalStatExcelDTO param) {
        return drgPatientCaseOutExtMapper.keyProjectsTotalStatPageCount(param);
    }

    public Page<DrgPatientCaseOutPO> patientAccessCostsAnalysis(PatientAccessCostsAnalysisDTO param) {
        LambdaQueryWrapper<DrgPatientCaseOutPO> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(param.getDepartCode())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getDepartCode, param.getDepartCode());
        }
        if (Objects.nonNull(param.getSettleStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getSettleDate, param.getSettleStartDate());
        }
        if (Objects.nonNull(param.getSettleEndDate())) {
            queryWrapper.le(DrgPatientCaseOutPO::getSettleDate, param.getSettleEndDate());
        }
        if (Objects.isNull(param.getSortType())) {
            queryWrapper.orderByDesc(DrgPatientCaseOutPO::getId);
        } else if (param.getSortType().equals(1)) {
            queryWrapper.orderByDesc(DrgPatientCaseOutPO::getDepartCode);
        } else if (param.getSortType().equals(2)) {
            queryWrapper.orderByDesc(DrgPatientCaseOutPO::getReimburseCost);
        } else {
            queryWrapper.orderByDesc(DrgPatientCaseOutPO::getSelfCost);
        }
        return getBaseMapper().selectPage(new Page<>(param.getPageIndex(), param.getPageSize()), queryWrapper);
    }

    public Page<DrgPatientCaseOutPO> auditResultsAnalysis(AuditResultsAnalysisDTO param) {
        LambdaQueryWrapper<DrgPatientCaseOutPO> queryWrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(param.getType())) {
            queryWrapper.eq(DrgPatientCaseOutPO::getMedicalType, param.getType());
        }
        if (Objects.nonNull(param.getStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getSettleDate, param.getStartDate());
        }
        if (Objects.nonNull(param.getEndDate())) {
            queryWrapper.le(DrgPatientCaseOutPO::getSettleDate, param.getEndDate());
        }
        queryWrapper.orderByDesc(DrgPatientCaseOutPO::getId);
        return getBaseMapper().selectPage(new Page<>(param.getPageIndex(), param.getPageSize()), queryWrapper);
    }

    public Page<DrgPatientCaseOutPO> singleDiseaseHospitalizationCostAnalysis(SingleDiseaseHospitalizationCostAnalysisDTO param) {
        LambdaQueryWrapper<DrgPatientCaseOutPO> queryWrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(param.getMedicareType())) {
        }
        if (Objects.nonNull(param.getStartDate())) {
            queryWrapper.ge(DrgPatientCaseOutPO::getSettleDate, param.getStartDate());
        }
        if (Objects.nonNull(param.getEndDate())) {
            queryWrapper.le(DrgPatientCaseOutPO::getSettleDate, param.getEndDate());
        }
        queryWrapper.orderByDesc(DrgPatientCaseOutPO::getId);
        return getBaseMapper().selectPage(new Page<>(param.getPageIndex(), param.getPageSize()), queryWrapper);
    }
}
